package org.cjstudio.holypoopsgrs.test;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.cjstudio.holypoopsgrs.model.UserProfile;
import org.cjstudio.holypoopsgrs.model.UserRecord;
import org.cjstudio.holypoopsgrs.server.Repository;
import org.cjstudio.holypoopsgrs.test.util.SampleData;
import org.cjstudio.holypoopsgrs.test.template.SpringAppEngineTest;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@ContextConfiguration("/testContext.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringTest2 extends SpringAppEngineTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		SpringAppEngineTest.tearDownAfterClass();

	}

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

	}

	@Override
	@After
	public void tearDown() throws Exception {
		super.tearDown();

	}


	@Resource
	private Repository<UserProfile> userProfileRepository = null;

	@Test
	public void retrieveAllTest_success() {
		List<UserProfile> profiles = new ArrayList<UserProfile>();
		List<Set<UserRecord>> records = new ArrayList<Set<UserRecord>>();
		//store sample profile
		for(int i=1; i<=100; i++) {
			UserProfile profile = SampleData.getSampleProfile(i);
			userProfileRepository.create(profile);

			Set<UserRecord> set = new HashSet<UserRecord>(profile.topTenRecords);
			records.add(set);

			profile.topTenRecords = null;
			profiles.add(profile);
		}

		//retrieve all profiles
		List<UserProfile> storedProfiles = userProfileRepository.retrieveAll();
		List<Set<UserRecord>> storedRecords = new ArrayList<Set<UserRecord>>();
		for(UserProfile storedProfile : storedProfiles) {
			Set<UserRecord> set = new HashSet<UserRecord>(storedProfile.topTenRecords);
			storedRecords.add(set);

			storedProfile.topTenRecords = null;
		}

		Assert.assertEquals(records.size(), storedRecords.size());
		Assert.assertTrue(storedRecords.containsAll(records));

		Assert.assertEquals(profiles.size(), storedProfiles.size());
		Assert.assertTrue(storedProfiles.containsAll(profiles));
	}

	@Test
	public void retrieveAllTest_fail() {
		List<UserProfile> storedProfiles = userProfileRepository.retrieveAll();
		Assert.assertNull(storedProfiles);
	}
	
	@Test
	public void retrieveWithRange_success() {
		List<UserProfile> profiles = new ArrayList<UserProfile>();
		List<Set<UserRecord>> records = new ArrayList<Set<UserRecord>>();
		//store sample profile
		for(int i=1; i<=50; i++) {
			UserProfile profile = SampleData.getSampleProfile(i-1);
			userProfileRepository.create(profile);

			if(i<=20) {
				Set<UserRecord> set = new HashSet<UserRecord>(profile.topTenRecords);
				records.add(set);

				profile.topTenRecords = null;
				profiles.add(profile);
			}
		}
		

		//retrieve all profiles
		List<UserProfile> storedProfiles = userProfileRepository.retrieveWithRange(1, 20);
		List<Set<UserRecord>> storedRecords = new ArrayList<Set<UserRecord>>();
		for(UserProfile storedProfile : storedProfiles) {
			Set<UserRecord> set = new HashSet<UserRecord>(storedProfile.topTenRecords);
			storedRecords.add(set);

			storedProfile.topTenRecords = null;
		}

		System.out.println(records.size() + "/" + storedRecords.size());
		System.out.println(records);
		System.out.println(storedRecords);
		Assert.assertEquals(records.size(), storedRecords.size());
		Assert.assertTrue(storedRecords.containsAll(records));

		System.out.println(profiles.size() + "/" + storedProfiles.size());
		System.out.println(profiles);
		System.out.println(storedProfiles);
		Assert.assertEquals(profiles.size(), storedProfiles.size());
		Assert.assertEquals(profiles, storedProfiles);
		
		
		Assert.assertTrue(profiles.containsAll(storedProfiles));
		
		// FIXME Why these two are not true even the prev is true...
		/*
		Assert.assertTrue(storedProfiles.containsAll(profiles));

		for(UserProfile storedProfile : storedProfiles) {
			System.out.println(storedProfile);
			Assert.assertTrue(profiles.contains(storedProfiles));
		}
		*/
		
	}
	
	@Test
	public void retrieveWithRange_success2() {
		List<UserProfile> profiles = new ArrayList<UserProfile>();
		List<Set<UserRecord>> records = new ArrayList<Set<UserRecord>>();
		//store sample profile
		for(int i=1; i<=10; i++) {
			UserProfile profile = SampleData.getSampleProfile(i-1);
			userProfileRepository.create(profile);

			Set<UserRecord> set = new HashSet<UserRecord>(profile.topTenRecords);
			records.add(set);

			profile.topTenRecords = null;
			profiles.add(profile);
		}
		

		//retrieve all profiles
		List<UserProfile> storedProfiles = userProfileRepository.retrieveWithRange(1, 20);
		List<Set<UserRecord>> storedRecords = new ArrayList<Set<UserRecord>>();
		for(UserProfile storedProfile : storedProfiles) {
			Set<UserRecord> set = new HashSet<UserRecord>(storedProfile.topTenRecords);
			storedRecords.add(set);

			storedProfile.topTenRecords = null;
		}

		System.out.println(records.size() + "/" + storedRecords.size());
		System.out.println(records);
		System.out.println(storedRecords);
		Assert.assertEquals(records.size(), storedRecords.size());
		Assert.assertTrue(storedRecords.containsAll(records));

		System.out.println(profiles.size() + "/" + storedProfiles.size());
		System.out.println(profiles);
		System.out.println(storedProfiles);
		Assert.assertEquals(profiles.size(), storedProfiles.size());
		Assert.assertEquals(profiles, storedProfiles);
		
		
		Assert.assertTrue(profiles.containsAll(storedProfiles));
		
		// FIXME Why these two are not true even the prev is true...
		/*
		Assert.assertTrue(storedProfiles.containsAll(profiles));

		for(UserProfile storedProfile : storedProfiles) {
			System.out.println(storedProfile);
			Assert.assertTrue(profiles.contains(storedProfiles));
		}
		*/
	}
}
